package za.org.foobar.famon.simpleui;

import za.org.foobar.famon.util.DBQuery;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspWriter;
import java.io.IOException;
import java.util.List;

/**
 *
 */
public class PageUtil {
    public static final String PARAM_PAGE_NUMBER = "_page";
    public static final String PARAM_ROWS_PER_PAGE = "_rows";
    private HttpServletRequest request;
    private String anchor;
    private int pageNumber;
    private int rowsPerPage;
    private long totalRows;
    private String paramPageNumber;
    private String paramRowsPerPage;
    private String paramRegex;

    public PageUtil(HttpServletRequest request, String name, String anchor) {
        this.request = request;
        this.anchor = anchor;
        paramPageNumber = name + PARAM_PAGE_NUMBER;
        paramRowsPerPage = name + PARAM_ROWS_PER_PAGE;
        pageNumber = SimpleUiUtil.getParameterInt(request, paramPageNumber, 0);
        rowsPerPage = SimpleUiUtil.getParameterInt(request, paramRowsPerPage, 50);
        paramRegex = "[\\&]((" + paramPageNumber + ")|(" + paramRowsPerPage + "))[\\=][\\d]+";
    }

    public PageUtil(HttpServletRequest request, String name) {
        this(request, name, null);
    }

    public PageUtil(HttpServletRequest request) {
        this(request, "page", null);
    }

    public long getPageStart() {
        return pageNumber * rowsPerPage;
    }

    public long getPageEnd() {
        return (pageNumber+1) * rowsPerPage;
    }

    public int getPageNumber() {
        return pageNumber;
    }

    public void setPageNumber(int pageNumber) {
        this.pageNumber = pageNumber;
    }

    public int getRowsPerPage() {
        return rowsPerPage;
    }

    public void setRowsPerPage(int rowsPerPage) {
        this.rowsPerPage = rowsPerPage;
    }

    public long getTotalRows() {
        return totalRows;
    }

    public void setTotalRows(long totalRows) {
        this.totalRows = totalRows;
    }

    public int getPageCount() {
        if (totalRows == 0) {
            return pageNumber + 1;
        }
        return (int)Math.ceil((double)totalRows / rowsPerPage);
    }

    public <T> List<T> getResultList(DBQuery<T> q, boolean checkTotalRows) {
        if (checkTotalRows) {
            return getResultList(q.getResultList());
        }
        return q.setRange(getPageStart(), getPageEnd()).getResultList();
    }

    public <T> List<T> getResultList(List<T> list) {
        totalRows = list.size();
        int toIndex = Math.min((int)getPageEnd(), (int)totalRows);
        int fromIndex = Math.min((int)getPageStart(), toIndex);
        return list.subList(fromIndex, toIndex);
    }

    public void printPagesTr(JspWriter out, int colspan) throws IOException {
        printPages(out, "<tr><td colspan=\"" + colspan + "\" class=\"paging\">", "</td></tr>");
    }

    public void printPages(JspWriter out, String prefix, String suffix) throws IOException {
        int count = getPageCount();
        if (pageNumber == 0 && count == 1 && totalRows != 0) {
            return;
        }

        out.append(prefix);
        if (pageNumber > 0) {
            getPageLink(out, pageNumber-1, "&lt;");
        }
        int i0 = Math.max(pageNumber - 5, 0);
        int i1 = Math.min(pageNumber + 5, count-1);
        if (i0 > 0) {
            out.append("<span>...</span>");
        }
        for (int i = i0; i <= i1; i++) {
            getPageLink(out, i, Integer.toString(i+1));
        }
        if (i1 < count - 1) {
            out.append("<span>...</span>");
        }
        if (pageNumber < count - 1 || totalRows == 0) {
            getPageLink(out, pageNumber+1, "&gt;");
        }
        out.append(suffix);
    }

    private void getPageLink(JspWriter out, int p, String str) throws IOException {
        if (p != pageNumber) {
            out.append("<a href=\"");
            getPageUrl(out, p);
            out.append("\">").append(str).append("</a>");
        } else {
            out.append("<span>[").append(str).append("]</span>");
        }
    }

    private void getPageUrl(JspWriter out, int p) throws IOException {
        String url = SimpleUiUtil.getCurrentUrl(request).replaceAll(paramRegex, "");
        out.append(url);
        out.append("&").append(paramPageNumber).append("=").append(Integer.toString(p));
        out.append("&").append(paramRowsPerPage).append("=").append(Integer.toString(rowsPerPage));
        if (anchor != null) {
            out.append("#").append(anchor);
        }
    }
}
